/*
*
==============================================================================
*  Name        : 
*  Part of     : Omen Game Engine
*  Description : 
*  Version     : 1.0
*
*  Copyright (c) 2013 Lauri Kortevaara.
* 
==============================================================================
*/

#pragma once

#include "OmenConfig.h"
#include "IOmenObject.h"
#include "OmenVector3d.h"
#include "OmenMatrix.h"
#include "OmenTransform.h"

namespace Omen
{
    class ICamera : public Omen::IObject
    {
    public:
        /// Camera projection type enumerations
        typedef enum
        {
            ProjectionType_Orthographic,
            ProjectionType_Perspective        /// <summary>This is the default projection of Omen::ICamera projection type</summary>
        } ProjectionType;

    public:
        virtual Omen_GUID classId() const = 0;    /// <summary>Defines the class ID</summary>
        
        ///        
        /// Camera projection type, perspective or orthogonal
        ///
        virtual void setPerspective( Omen::Float fov, Omen::Float aspect, Omen::Float znear, Omen::Float zfar ) = 0;
        virtual void setOrtho( Omen::Float left, Omen::Float right, Omen::Float bottom, Omen::Float top, Omen::Float near, Omen::Float far ) = 0;

        ///
        /// Camera transform
        ///
        virtual const Omen::Transform& transform() const = 0;
        virtual Omen::Transform& transform() = 0;

        ///
        /// Camera position and 
        ///
        virtual Omen::Vector3d    position() const = 0;                     /// <summary> Returns the position vector in world coordinates</summary>
        virtual void  setPosition(const Omen::Vector3d& position) = 0;      /// <summary> Set the camera position in global coordinates

        ///
        /// Set position and look at direction with setLookAT
        ///
        virtual void  setLookAt(const Omen::Vector3d& target) = 0;          /// <summary> Set the camera target coordinate, where the camera is looking at</summary>
        
        ///
        /// Orthonormal direction base vectors
        ///
        virtual Omen::Vector3d    right() const = 0;                        /// <summary> Returns the normalized direction vector pointing up </summary>
        virtual Omen::Vector3d    up() const = 0;                           /// <summary> Returns the normalized direction vector pointing up </summary>
        virtual Omen::Vector3d    forward() const = 0;                      /// <summary> Returns the normalized direction vector pointing forward</summary>

        virtual void  setRight(const Omen::Vector3d& up)  = 0;              /// <summary> Set the camera right-direction</summary>
        virtual void  setUp(const Omen::Vector3d& up) = 0;                  /// <summary> Set the camera up-direction</summary>
        virtual void  setForward(const Omen::Vector3d& up)  = 0;            /// <summary> Set the camera forward-direction</summary>

        ///
        /// Roatation angles
        ///
        virtual Omen::Float pitch() const = 0;                              /// <summary> The angle in degrees around the x-axis, turning from from down-to-up e.g. clock-wise</summary>
        virtual Omen::Float yaw() const = 0;                                /// <summary> The angle in degres around the y-axis, turning from right-to-left e.g. clock-wise</summary>
        virtual Omen::Float roll() const = 0;                               /// <summary> The angle in degres around the z-axis, turning clock-wise</summary>

        virtual void setPitch( Omen::Float pitch) = 0;                      /// <summary> The angle in degrees around the x-axis, turning from from down-to-up e.g. clock-wise</summary>
        virtual void setYaw( Omen::Float yaw) = 0;                          /// <summary> The angle in degres around the y-axis, turning from right-to-left e.g. clock-wise</summary>
        virtual void setRoll(Omen::Float roll) = 0;                         /// <summary> The angle in degres around the z-axis, turning clock-wise</summary>

        ///
        /// Velocity and acceleration
        ///
        virtual Omen::Vector3d velocity() const = 0;                        /// <summary> Returns the velocity of the camera </summary>
        virtual Omen::Vector3d maxVelocity() const = 0;                     /// <summary> Returns the maximum camera velocity </summary>
        virtual Omen::Vector3d acceleration() const = 0;                    /// <summary> Returns the acceleration of the camera</summary>

        virtual void setVelocity( const Omen::Vector3d& velocity ) = 0;      /// <summary> Set's the current camera velocity </summary>
        virtual void setMaxVelocity( const Omen::Vector3d& velocity ) = 0;  /// <summary> Set's the velocity of the camera</summary>
        virtual void setAcceleration( const Omen::Vector3d& acceleration ) = 0; /// <summary> Set's the acceleration of the camera</summary>

        ///
        /// Position update function
        ///
        virtual void updatePosition(const Vector3d& direction, Omen::Float elapsedTime) = 0; /// <summary> Updates the camera position according to it's direction and velocity </summary>

        ///
        /// Camera rotation speed
        ///
        virtual Omen::Float rotationSpeed() const = 0;                      /// <summary> Returns the rotation speed of the camera </summary>
        virtual void setRotationSpeed( Omen::Float speed ) = 0;             /// <summary> Sets the rotation speed of the camera </summary>

        ///
        /// Camera view matrix
        ///
        virtual void getViewMatrix( Omen::Matrix4x4& viewMatrix ) = 0;         /// <summary> Get the view matrix from the camera </summary>
        virtual void setViewMatrix( const Omen::Matrix4x4& viewMatrix ) = 0; /// <summary> Sets the view matrix for this camera </summary>
        
        ///
        /// Camera projection matrix
        ///
        virtual void getProjectionMatrix( Omen::Matrix4x4& projectionMatrix ) = 0;         /// <summary>Get the projection matrix from this camera</summary>
        virtual void setProjectionMatrix( const Omen::Matrix4x4& projectionMatrix ) = 0; /// <summary>Sets the projection matrix for this camera </summary>

        virtual ICamera::ProjectionType projectionType() const = 0; /// <summary> Returns the projection type of the camera, either perspective or orthographic </summary>
        
        /// 
        /// Update camera matrix
        ///
        virtual void updateCameraMatrix() = 0;

        ///
        /// Camera bounding volume
        ///
        virtual Omen::IBoundingVolume* boundingVolume( Omen::Float dTime ) = 0;

    protected:        
    private:
    };
}